#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include "cgi_interface.h"
#include "global_val.h"
#include "alarm_task.h"
#include "alarm_task_list.h"
#include "sql.h"


int (*alarm_cb_array[]) (const char *, const unsigned char) ={NULL, NULL, NULL, NULL, NULL, NULL, CGI_Led_Control_RE, NULL, NULL, CGI_Door_Control, CGI_Fan_Control, CGI_Beep_Control, NULL, CGI_Calorifier_Control, CGI_Curtain_Control};
alarm_task_head_t *alarm_task_list_head;
int alarm_count=0;

/*********************************************************************
 * @fn      alarm_task_list_init
 *
 * @brief   初始化alarm_task任务
 *
 * @param   none
 *
 * @return  none
 */
void alarm_task_list_init(void)
{
	time_t tNow;
    struct tm *ptm;
	
    alarm_task_list_head = alarm_task_creat_head();

    //数据库读取数据 建立alarm_task_list
    alarm_task_list_create();

	while(1)
	{
		tNow = time(NULL);
		ptm  = localtime(&tNow);
		if(ptm->tm_sec==0)
			break;
	}
	
    signal(SIGALRM, signal_sigalarm_handle);
    alarm(60);
}

/*********************************************************************
 * @fn      alarm_task_list_create
 *
 * @brief   创建alarm_task链表
 *
 * @param   none
 *
 * @return  none
 */
void alarm_task_list_create(void)
{
    char sql_buf[16][10][256];
    int col[]={0, 2, 3, 4, 5, 6, 7};
    char type[]={SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_STR, SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_STR, SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_INT};
    int i,j,k,res,result;
    alarm_info_t *node;

    res = sql_get_table_nfield("alarm_task", col, type, 7, sql_buf);
    for(i=0; i<res; ++i)
    {
        node = (alarm_info_t *)malloc(sizeof(alarm_info_t));

        //alarm_id
        result         = str_to_int(sql_buf[i][0]);
        node->alarm_id = result;
        //dev_mac
        strcpy(node->mac, sql_buf[i][1]);
        //sensor_type(alarm_cb)
        result         = str_to_int(sql_buf[i][2]);
        node->alarm_cb = alarm_cb_array[result];
        //sensor_status
        result       = str_to_int(sql_buf[i][3]);
        node->status = result;
        //alarm_time
        strcpy(node->alarm_time, sql_buf[i][4]);
        //alarm_switch
        result             = str_to_int(sql_buf[i][5]);
        node->alarm_switch = result;
        //alarm_switch
        result             = str_to_int(sql_buf[i][6]);
        node->alarm_repeat = result;
        //insert node
        insert_alarm_task(alarm_task_list_head, node);
        free(node);
    }
}

/*********************************************************************
 * @fn      alarm_task_list_update
 *
 * @brief   更新alarm_task链表线程函数
 *
 * @param   none
 *
 * @return  none
 */
void *alarm_task_list_update(void *arg)
{
	del_alarm_task_msg del_alarm_task_pkg;
	
	while(1)
	{
		//等待信号
        poperation(sem_update_alarm_task, g_sem_id);
		printf("task_list recreate!\n");
		//释放链表
		free_alarm_task(alarm_task_list_head);
		//从数据库中读取新数据重新生成链表
		alarm_task_list_head = alarm_task_creat_head();
		alarm_task_list_create();
	}
}

/*********************************************************************
 * @fn      pthread_get_clock_msg
 *
 * @brief   获取闹钟消息线程处理函数
 *
 * @param   none
 *
 * @return  none
 */
void *pthread_get_clock_msg(void *arg)
{
    char sql_dat[10][32];
    // ID dev_mac sensor_type sensor_status alarm_time alarm_switch alarm_repeat
    char type[]={SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_STR, SQL_FIEL_TYPE_STR, SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_STR, SQL_FIEL_TYPE_INT, SQL_FIEL_TYPE_INT};
    alarm_task_msg_pkg alarm_msg;
    alarm_info_t *node;

    alarm_task_list_init();
    while(1)
    {
        //等待信号
        poperation(sem_alarm_task_list, g_sem_id);

        //提取消息
        poperation(sem_msg_queue_qt_id, g_sem_id);//消息队列读写锁
        msgrcv(g_msgid, (void *)&alarm_msg, sizeof(alarm_task_msg_pkg)-sizeof(long int), MSG_QUEUE_ALARM_TYPE, IPC_NOWAIT);
        voperation(sem_msg_queue_qt_id, g_sem_id);

        //写入数据库
        sprintf(sql_dat[0], "%s", "NULL");
        sprintf(sql_dat[1], "%s", alarm_msg.name);
        sprintf(sql_dat[2], "%s", alarm_msg.mac);
        sprintf(sql_dat[3], "%d", alarm_msg.type);
        //printf("dev_type=%d set_status=%d\n", alarm_msg.type, alarm_msg.status);
        if(alarm_msg.type==CMD_LIGHT||alarm_msg.type==CMD_RELAY||alarm_msg.type==CMD_CALORIFIER||alarm_msg.type==CMD_CURTAIN)
        {
            //on-0 off-1
            alarm_msg.status = alarm_msg.status==0?1:0;
        }
        sprintf(sql_dat[4], "%d", alarm_msg.status);
        sprintf(sql_dat[5], "%s", alarm_msg.alarm_time);
        sprintf(sql_dat[6], "%d", alarm_msg.alarm_status);
        sprintf(sql_dat[7], "%d", alarm_msg.alarm_repeat);
        insert_line_data("alarm_task", sql_dat, type, 8);
        //获取ID最大值(alarm_id)
        alarm_count = sql_get_intfield_maxvalue("alarm_task", "ID");

        //新建节点
        node = (alarm_info_t *)malloc(sizeof(alarm_info_t));
        strcpy(node->mac, alarm_msg.mac);
        strcpy(node->alarm_time, alarm_msg.alarm_time);
        node->alarm_id     = alarm_count;
        node->status       = alarm_msg.status;
        node->alarm_switch = alarm_msg.alarm_status;
        node->alarm_repeat = alarm_msg.alarm_repeat;
        node->alarm_cb     = alarm_cb_array[alarm_msg.type];
        insert_alarm_task(alarm_task_list_head, node);
        free(node);
    }
}

/*********************************************************************
 * @fn      pthread_del_alarm_task
 *
 * @brief   删除alarm_task上的一个节点 等待信号量触发
 *
 * @param   none
 *
 * @return  none
 */
void *pthread_del_alarm_task(void *arg)
{
    del_alarm_task_msg del_alarm_task_pkg;

    while(1)
    {
        poperation(sem_del_alarm_task, g_sem_id);
        //提取消息
        poperation(sem_msg_queue_qt_id, g_sem_id);//消息队列读写锁
        msgrcv(g_msgid, (void *)&del_alarm_task_pkg, sizeof(del_alarm_task_msg)-sizeof(long int), MSG_QUEUE_DEL_ALARM_TYPE, IPC_NOWAIT);
        voperation(sem_msg_queue_qt_id, g_sem_id);

        printf("free id:%d\n", del_alarm_task_pkg.del_alarm_task_id);
        free_alarm_node(alarm_task_list_head, del_alarm_task_pkg.del_alarm_task_id);
    }
}

/*********************************************************************
 * @fn      signal_sigalarm_handle
 *
 * @brief   alarm函数的回调函数
 *
 * @param   none
 *
 * @return  none
 */
void signal_sigalarm_handle(int sig)
{
    //定时遍历闹钟任务链表
    printf("signal:SIGLARM\n");
    loop_alarm_task(alarm_task_list_head);
    alarm(60);
}
